using System;
using System.Globalization;
using System.IO;
using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Tasks;
using NAnt.Core.Util;

[TaskName("foreach2")]
public class LoopTask : TaskContainer
{
	// Fields
	private string _delim;
	private TaskContainer _doStuff;
	private string _inAttribute;
	private InElement _inElement;
	private LoopItem _loopItem;
	private LoopTrim _loopTrim = LoopTrim.None;
	private string _prop;
	private string[] _props;

	// Methods
	protected virtual void DoWork(params string[] propVals)
	{
		for (int i = 0; i < propVals.Length; i++)
		{
			string str = propVals[i];
			if (i >= _props.Length)
			{
				throw new BuildException("Too many items on line", Location);
			}
			switch (TrimType)
			{
				case LoopTrim.End:
					str = str.TrimEnd(new char[0]);
					break;

				case LoopTrim.Start:
					str = str.TrimStart(new char[0]);
					break;

				case LoopTrim.Both:
					str = str.Trim();
					break;
			}
			Properties[_props[i]] = str;
		}
		base.ExecuteTask();
	}

	private void DoWorkOnFileLines(string filename)
	{
		using (StreamReader reader = File.OpenText(filename))
		{
			string str;
			Label_0009:
			str = reader.ReadLine();
			if (str != null)
			{
				if (Delimiter == null)
				{
					DoWork(new string[] {str});
				}
				else
				{
					DoWork(str.Split(Delimiter.ToCharArray()));
				}
				goto Label_0009;
			}
		}
	}

	protected override void ExecuteChildTasks()
	{
		if (StuffToDo == null)
		{
			base.ExecuteChildTasks();
		}
		else
		{
			StuffToDo.Execute();
		}
	}

	protected override void ExecuteTask()
	{
		string[] strArray = new string[_props.Length];
		for (int i = 0; i < strArray.Length; i++)
		{
			strArray[i] = Properties[_props[i]];
		}
		try
		{
			switch (ItemType)
			{
				case LoopItem.File:
					if (StringUtils.IsNullOrEmpty(Source) && (InElement == null))
					{
						throw new BuildException("Invalid foreach", Location, new ArgumentException("Nothing to work with...!", "in"));
					}
					break;

				case LoopItem.Folder:
					if (StringUtils.IsNullOrEmpty(Source) && (InElement == null))
					{
						throw new BuildException("Invalid foreach", Location, new ArgumentException("Nothing to work with...!", "in"));
					}
					goto Label_01F3;

				case LoopItem.String:
					if (!StringUtils.IsNullOrEmpty(Source))
					{
						goto Label_0456;
					}
					return;

				case LoopItem.Line:
					if (StringUtils.IsNullOrEmpty(Source) && (InElement == null))
					{
						throw new BuildException("Invalid foreach", Location, new ArgumentException("Nothing to work with...!", "in"));
					}
					goto Label_035C;

				default:
					return;
			}
			if (!StringUtils.IsNullOrEmpty(Source))
			{
				Source = Project.GetFullPath(Source);
				if (!Directory.Exists(Source))
				{
					throw new BuildException(
						string.Format(CultureInfo.InvariantCulture, ResourceUtils.GetString("NA1134"), new object[] {Source}), Location);
				}
				if (_props.Length != 1)
				{
					throw new BuildException("Only one property is valid for item=\"File\"", Location);
				}
				DirectoryInfo info = new DirectoryInfo(Source);
				foreach (FileInfo info2 in info.GetFiles())
				{
					DoWork(new string[] {info2.FullName});
				}
			}
			else
			{
				if (StuffToDo == null)
				{
					throw new BuildException("Must use <do> with <in>.", Location);
				}
				foreach (string str in InElement.Items.FileNames)
				{
					DoWork(new string[] {str});
				}
			}
			return;
			Label_01F3:
			if (_props.Length != 1)
			{
				throw new BuildException("Only one property is valid for item=\"Folder\"", Location);
			}
			if (!StringUtils.IsNullOrEmpty(Source))
			{
				Source = Project.GetFullPath(Source);
				if (!Directory.Exists(Source))
				{
					throw new BuildException(
						string.Format(CultureInfo.InvariantCulture, ResourceUtils.GetString("NA1134"), new object[] {Source}), Location);
				}
				DirectoryInfo info3 = new DirectoryInfo(Source);
				foreach (DirectoryInfo info4 in info3.GetDirectories())
				{
					DoWork(new string[] {info4.FullName});
				}
			}
			else
			{
				if (StuffToDo == null)
				{
					throw new BuildException("Must use <do> with <in>.", Location);
				}
				foreach (string str2 in InElement.Items.DirectoryNames)
				{
					DoWork(new string[] {str2});
				}
			}
			return;
			Label_035C:
			if ((_props.Length > 1) && (Delimiter == null))
			{
				throw new BuildException("Delimiter(s) must be specified if multiple properties are specified", Location);
			}
			if (!StringUtils.IsNullOrEmpty(Source))
			{
				Source = Project.GetFullPath(Source);
				if (!File.Exists(Source))
				{
					throw new BuildException(
						string.Format(CultureInfo.InvariantCulture, ResourceUtils.GetString("NA1133"), new object[] {Source}), Location);
				}
				DoWorkOnFileLines(Source);
			}
			else
			{
				if (StuffToDo == null)
				{
					throw new BuildException("Must use <do> with <in>.", Location);
				}
				foreach (string str3 in InElement.Items.FileNames)
				{
					DoWorkOnFileLines(str3);
				}
			}
			return;
			Label_0456:
			if (_props.Length > 1)
			{
				throw new BuildException("Only one property may be specified for item=\"String\"", Location);
			}
			if (Delimiter == null)
			{
				throw new BuildException("Delimiter must be specified for item=\"String\"", Location);
			}
			foreach (string str4 in Source.Split(Delimiter.ToCharArray()))
			{
				DoWork(new string[] {str4});
			}
		}
		finally
		{
			for (int j = 0; j < strArray.Length; j++)
			{
				Properties[_props[j]] = strArray[j];
			}
		}
	}

	// Properties
	[TaskAttribute("delim")]
	public string Delimiter
	{
		get { return _delim; }
		set
		{
			if ((value == null) || (value.Length == 0))
			{
				_delim = null;
			}
			else
			{
				_delim = value;
			}
		}
	}

	[BuildElement("in")]
	public InElement InElement
	{
		get { return _inElement; }
		set { _inElement = value; }
	}

	[TaskAttribute("item", Required=true)]
	public LoopItem ItemType
	{
		get { return _loopItem; }
		set { _loopItem = value; }
	}

	[StringValidator(AllowEmpty=false), TaskAttribute("property", Required=true)]
	public string Property
	{
		get { return _prop; }
		set
		{
			_prop = value;
			_props = _prop.Split(new char[] {','});
			foreach (string str in _props)
			{
				if (Properties.IsReadOnlyProperty(str))
				{
					throw new BuildException("Property is readonly! :" + str, Location);
				}
			}
		}
	}

	[TaskAttribute("in", Required=false)]
	public string Source
	{
		get { return _inAttribute; }
		set { _inAttribute = StringUtils.ConvertEmptyToNull(value); }
	}

	[BuildElement("do")]
	public TaskContainer StuffToDo
	{
		get { return _doStuff; }
		set { _doStuff = value; }
	}

	[TaskAttribute("trim")]
	public LoopTrim TrimType
	{
		get { return _loopTrim; }
		set { _loopTrim = value; }
	}

	// Nested Types
	public enum LoopItem
	{
		File = 1,
		Folder = 2,
		Line = 4,
		String = 3
	}

	public enum LoopTrim
	{
		None,
		End,
		Start,
		Both
	}
}